package util;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Properties;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;


/**
 * xml锟侥碉拷锟斤拷锟斤拷夭锟斤拷锟� * @author hucy Create on 2007-12-27 16:38:42
 */
public class XmlManager {
	
//	private static Logger logger= LoggerFactory.getLogger(XmlManager.class);

	public static Document createDomByString(String xmldata) {
		try {

			return getDom(xmldata);
		} catch (Exception ex) {
//			logger.error(ex.toString(),ex);
			return null;
		}
	}

	public static Document createDomByString(String xmldata,
			EntityResolver entityresolver) {
		try {

			return getDom(new StringReader(xmldata), entityresolver);
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	public static Document createDom(String strFileName, String encoding) {
		try {
			FileInputStream fis = new FileInputStream(strFileName);
			byte[] bytebuf = new byte[fis.available()];
			fis.read(bytebuf);
			fis.close();
			return getDom(new String(bytebuf, encoding));
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}

	}

	public static Document createDom(String strFileName, String encoding,
			EntityResolver entityresolver) {
		try {
			FileInputStream fis = new FileInputStream(strFileName);
			Document doc = getDom(new InputStreamReader(fis, encoding),
					entityresolver);
			fis.close();
			return doc;
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}

	}

	public static Document createDom(Reader reader) {
		try {
			return getDom(reader);
		} catch (Exception ex) {
			System.out.println(ex);
			return null;
		}

	}

	public static final Document getDom(Reader reader,
			EntityResolver entityresolver) {
		try {
			// 锟狡筹拷xcerse 锟斤拷锟斤拷锟斤拷
//			String xmlparse = (String) System.getProperties().remove(
//					"javax.xml.parsers.DocumentBuilderFactory");
//			System.getProperties().put(
//					"javax.xml.parsers.DocumentBuilderFactory",
//					"org.apache.crimson.jaxp.DocumentBuilderFactoryImpl");
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//			System.getProperties().remove(
//					"javax.xml.parsers.DocumentBuilderFactory");
//			if (xmlparse != null) {
//				System.getProperties().put(
//						"javax.xml.parsers.DocumentBuilderFactory", xmlparse);
//			}

			dbf.setCoalescing(true);
			dbf.setNamespaceAware(true);
			dbf.setIgnoringElementContentWhitespace(true);

			// dbf.setValidating(false);
			DocumentBuilder db = dbf.newDocumentBuilder();
			if (entityresolver != null)
				db.setEntityResolver(entityresolver);
			Document doc = db.parse(new InputSource(reader));
			return doc;
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	protected static final Document getDom(Reader reader) {
		try {

			Document doc = getDom(reader, null);
			return doc;
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	protected static final Document getDom(String xmldata) {
		try {
			if (xmldata == null || xmldata.trim().length() == 0)
				return null;
			
			Document doc = getDom(new StringReader(xmldata));

			return doc;

		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	public static NodeList queryList(String strXPath, Node node,
			NamespaceContext namespace) {
		try {
			XPath xpath = getXPath();
			if (namespace != null)
				xpath.setNamespaceContext(namespace);
			return (NodeList) xpath.evaluate(strXPath, node,
					XPathConstants.NODESET);
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	public static NodeList queryList(String strXPath, Node node) {
		return queryList(strXPath, node, null);
	}

	public static Node querySingle(String xPath, Node node,
			NamespaceContext namespace) {
		try {
			XPath xpath = getXPath();
			if (namespace != null)
				xpath.setNamespaceContext(namespace);
			return (Node) xpath.evaluate(xPath, node, XPathConstants.NODE);
		} catch (Exception ex) {
			//logger.error(ex.toString(),ex);
			return null;
		}
	}

	public static Node querySingle(String xPath, Node node) {
		return querySingle(xPath, node, null);
	}

	public static String querySingleValue(String xPath, Node node) {
		Node sinnode = querySingle(xPath, node);
		if (sinnode != null && sinnode.getNodeType() == Node.ATTRIBUTE_NODE)
			return sinnode.getNodeValue();
		else if (sinnode != null && sinnode.getFirstChild() != null)
			return sinnode.getFirstChild().getNodeValue();
		else
			return null;
	}
	
	private static XPathFactory xpathFact;
	static{
		xpathFact = XPathFactory.newInstance();
	}

	private static synchronized XPath getXPath() {
		return xpathFact.newXPath();
	}

	public static String Serialize(Node srcNode) {
		try{
		
			DOMSource doms = new DOMSource( srcNode );
			StringWriter strW = new StringWriter();
			StreamResult result = new StreamResult( strW );
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			Properties properties = transformer.getOutputProperties();
			properties.setProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
			properties.setProperty( OutputKeys.METHOD, "xml" );
			properties.setProperty( OutputKeys.INDENT, "yes" );
			transformer.setOutputProperties( properties );
			transformer.transform( doms, result );
			return strW.toString();
		}catch(Exception ex){
			//logger.error(ex.toString(),ex);
			return null;
		}
		
	}
	
	public static void writeDom(Document dom,String fileName,String encoding){
		try{
			FileOutputStream fis = null;
			OutputStreamWriter osw = null;
			try{
				fis = new FileOutputStream(fileName);
				osw = new OutputStreamWriter( fis,encoding );
				DOMSource doms = new DOMSource( dom );
				StreamResult result = new StreamResult( osw );
				TransformerFactory tf = TransformerFactory.newInstance();
				Transformer transformer = tf.newTransformer();
				Properties properties = transformer.getOutputProperties();
				properties.setProperty(OutputKeys.ENCODING, encoding );
				properties.setProperty( OutputKeys.METHOD, "xml" );
				properties.setProperty( OutputKeys.INDENT, "yes" );
				transformer.setOutputProperties( properties );
				transformer.transform( doms, result );
			}finally{
				if(osw != null) osw.close();
				if(fis != null) fis.close();
			}
			
		}catch(Exception ex){
			//logger.error(ex.toString(),ex);
		}
	}

}
